﻿using System;
using System.Collections.Generic;
using System.Globalization;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core.Request;
using Casamiel.API.Infrastructure;
using Casamiel.Application;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NLog;
using PaySharp.Alipay;
using PaySharp.Wechatpay;
using PaySharp.Wechatpay.Request;


namespace Casamiel.API.Application.Services
{
	/// <summary>
	/// Pay gate way service.
	/// </summary>
	public class PayGateWayService : IPayGateWayService
    {
 
        private readonly NLog.ILogger logger = LogManager.GetLogger("BizInfo");
        private readonly IPaymentService _paymentService;
        private readonly IIcApiService _iicApiService;
        private readonly IUserLogService _userLog;
        private readonly IMemberCardRepository _memberCard;
         
        private readonly CasamielSettings _settings;
        private readonly WxPayAppSettings _wxPayAppSettings;
        private readonly List<MiniAppSettings> _listminiAppSettings;
        private readonly WxPaySettigs _wxPaySettigs;
        private readonly AlipayService _alipayService;
        
        /// <summary>
        /// Gets the configuration.
        /// </summary>
        /// <value>The configuration.</value>
        public IConfiguration Configuration { get; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Casamiel.API.Application.Services.PayGateWayService"/> class.
        /// </summary>
        /// <param name="minioptionsSnapshot">Minioptions snapshot.</param>
        /// <param name="settings">Settings.</param>
        /// <param name="optionsSnapshot">Options snapshot.</param>
        /// <param name="payment">Payment.</param>
        /// <param name="iicApiService">Iic API service.</param>
        /// <param name="userLog">User log.</param>
        /// <param name="alipayService"></param>
        /// <param name="memberCard">Member card.</param>
        /// <param name="configuration">Configuration.</param>
        /// <param name="wxpaySettings">Wxpay settings.</param>
        public PayGateWayService(IOptionsSnapshot<List<MiniAppSettings>> minioptionsSnapshot, IOptionsSnapshot<CasamielSettings> settings, IOptionsSnapshot<WxPayAppSettings> optionsSnapshot
            , IPaymentService payment,
            IIcApiService iicApiService,
            IUserLogService userLog, AlipayService alipayService,
            IMemberCardRepository memberCard,   IConfiguration configuration, IOptionsSnapshot<WxPaySettigs> wxpaySettings)
        {
            if (minioptionsSnapshot == null) {
                throw new ArgumentNullException(nameof(minioptionsSnapshot));
            }

            if (settings == null) {
                throw new ArgumentNullException(nameof(settings));
            }

            if (optionsSnapshot == null) {
                throw new ArgumentNullException(nameof(optionsSnapshot));
            }

            if (wxpaySettings == null) {
                throw new ArgumentNullException(nameof(wxpaySettings));
            }

            _listminiAppSettings = minioptionsSnapshot.Value;
            _wxPayAppSettings = optionsSnapshot.Value;
            
            this._paymentService = payment;
            
            _iicApiService = iicApiService;
            _userLog = userLog;
            _memberCard = memberCard;
            _settings = settings.Value;
            
            Configuration = configuration;
            _wxPaySettigs = wxpaySettings.Value;
            _alipayService = alipayService;
            
        }
        /// <summary>
        /// 支付宝app支付
        /// </summary>
        /// <returns>The alipay order.</returns>
        /// <param name="amount"></param>
        /// <param name="outTradeNo"></param>
        /// <param name="shopname"></param>
        /// <param name="shopid"></param>
        public string CreateAlipayOrder(string outTradeNo, double amount, string shopname, string shopid)
        { 
            if (string.IsNullOrEmpty(shopname)) {
                shopname = "";
            }

            var request = new PaySharp.Alipay.Request.AppPayRequest();
            request.AddGatewayData(new PaySharp.Alipay.Domain.AppPayModel() {
                Body = _settings.Subject + shopname,
                TotalAmount = amount,
                Subject = _settings.Subject + (shopname.Length > 0 ? "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture) : ""),
                OutTradeNo = outTradeNo,
                StoreId = shopid,
                TimeoutExpress = "10m",

            });
            var merchant = new PaySharp.Alipay.Merchant() {
                AppId = Configuration.GetSection("AlipaySettings").GetValue<string>("AppId"),// "2018012302035911",
                NotifyUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("NotifyUrl"),//"http://xiaoha.zicp.net:10154/Notify",//
                ReturnUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("ReturnUrl"),//"http://xiaoha.zicp.net:10154/Notify1",//
                AlipayPublicKey = Configuration.GetSection("AlipaySettings").GetValue<string>("AlipayPublicKey"),
                Privatekey = Configuration.GetSection("AlipaySettings").GetValue<string>("Privatekey")
            };

            PaySharp.Alipay.AlipayGateway ga = new AlipayGateway(merchant);
            var response = ga.Execute(request);
            return response.OrderInfo;
             
        }


        /// <summary>
        ///  支付宝 小程序支付
        /// </summary>
        /// <param name="buyerid"></param>
        /// <param name="outTradeNo"></param>
        /// <param name="amount"></param>
        /// <param name="shopname"></param>
        /// <param name="shopid"></param>
        /// <returns></returns>
        public string CreateAlipayAppletOrder(string buyerid, string outTradeNo, double amount, string shopname, string shopid)
        {
            if (string.IsNullOrEmpty(shopname)) {
                shopname = "";
            }

            //AlipayTradeCreateModel model = new AlipayTradeCreateModel {
            //    Body = "可莎",
            //    Subject = "可莎",
            //    TotalAmount = "0.01",
            //    OutTradeNo = $"{DateTime.Now.ToString("yyyyMMddHHmmssffff")}",
            //    // ProductCode = "FACE_TO_FACE_PAYMENT",
            //    StoreId = "13",
            //    TimeoutExpress = "20m",
            //    BuyerId = "2088002520735822"

            //};
            var request = new AlipayTradeCreateRequest();
            request.SetProdCode("FACE_TO_FACE_PAYMENT");
            request.BizContent = JsonConvert.SerializeObject(new { buyer_id = buyerid, seller_id = _alipayService.Options.Uid,
                out_trade_no = outTradeNo, total_amount = amount.ToString(),
                subject = _settings.Subject + (shopname.Length > 0 ? "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture) : ""),
                body = _settings.Subject + shopname,
                storeid = shopid,
                timeout_express = "10m" });

            //request.SetBizModel(model);
            request.SetNotifyUrl(Configuration.GetSection("AlipaySettings").GetValue<string>("NotifyUrl").Replace("Notify", "AlipayAppletNotify"));
            var oauthTokenResponse = _alipayService.Execute(request);
            return oauthTokenResponse.TradeNo;
           
        }



        /// <summary>
        ///微信App支付
        /// </summary>
        /// <returns>The wechatpay order.</returns>
        /// <param name="outTradeNo">Out trade no.</param>
        /// <param name="amount">Amount.</param>
        /// <param name="shopname"></param>
        /// <param name="shopno"></param>


        public string CreateWechatpayOrder(string outTradeNo, double amount, string shopname, string shopno)
        {
            if (string.IsNullOrEmpty(shopname)) {
                shopname = "";
            }
            // var order = new ICanPay.Wechatpay.Order()
            //{
            //    Amount = amount,
            //    OutTradeNo = outTradeNo,
            //    Body = _settings.Subject,
            //    OpenId = "",
            //    TimeExpire = DateTime.Now.AddMinutes(5).ToString("yyyyMMddHHmmss")
            //};
            //var wechatpayMerchant = new ICanPay.Wechatpay.Merchant
            //{
            //    AppId = _wxPayAppSettings.AppId,
            //    MchId = _wxPayAppSettings.MchId,
            //    Key = _wxPayAppSettings.Key,
            //    AppSecret = _wxPayAppSettings.AppSecret,
            //    SslCertPath = _wxPayAppSettings.SslCertPath,//"Certs/apiclient_cert.p12",
            //    SslCertPassword = _wxPayAppSettings.SslCertPassword,// "1233410002",
            //    NotifyUrl = _wxPayAppSettings.NotifyUrl,
            //};
            //WechatpayGateway ga = new WechatpayGateway(wechatpayMerchant);
            //ga.Order = order;
            //ga.GatewayTradeType = GatewayTradeType.App;
            //return ga.Payment(order);
            var gateway1 = new PaySharp.Wechatpay.Merchant {
                AppId = _wxPayAppSettings.AppId,
                MchId = _wxPayAppSettings.MchId,
                Key = _wxPayAppSettings.Key,
                AppSecret = _wxPayAppSettings.AppSecret,
                SslCertPath = _wxPayAppSettings.SslCertPath,//"Certs/apiclient_cert.p12",
                SslCertPassword = _wxPayAppSettings.SslCertPassword,// "1233410002",
                NotifyUrl = _wxPayAppSettings.NotifyUrl,
            };

            WechatpayGateway ga = new WechatpayGateway(gateway1);
            var request = new AppPayRequest();
            var SceneInfo = new { store_info = new { id = shopno, name = shopname } };
            request.AddGatewayData(new PaySharp.Wechatpay.Domain.AppPayModel() {
                Attach = _settings.Subject + "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture),
                Body = _settings.Subject + "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture),
                TotalAmount = (amount * 100).ToInt32(0),
                OutTradeNo = outTradeNo,
                SceneInfo = JsonConvert.SerializeObject(SceneInfo),
                DeviceInfo = shopno
            });

            var response = ga.Execute(request);
            logger.Trace($"{JsonConvert.SerializeObject(response)}");
            return response.OrderInfo;
        }
        /// <summary>
        /// Creates the public we.
        /// </summary>
        /// <returns>The public we.</returns>
        /// <param name="outTradeNo">Out trade no.</param>
        /// <param name="amount">Amount.</param>
        /// <param name="openId">Open identifier.</param>
        public string CreatePublicWechatPay(string outTradeNo, double amount, string openId)
        {
            var merchart = new PaySharp.Wechatpay.Merchant {
                AppId = _wxPaySettigs.AppId,
                MchId = _wxPaySettigs.MchId,
                Key = _wxPaySettigs.Key,
                AppSecret = _wxPaySettigs.AppSecret,
                SslCertPath = _wxPaySettigs.SslCertPath,//"Certs/apiclient_cert.p12",
                SslCertPassword = _wxPaySettigs.SslCertPassword,// "1233410002",
                NotifyUrl = _wxPaySettigs.NotifyUrl,
            };
            WechatpayGateway _gateway = new WechatpayGateway(merchart);
            var request = new PublicPayRequest();
            request.NotifyUrl = _wxPaySettigs.NotifyUrl;
            request.AddGatewayData(new PaySharp.Wechatpay.Domain.PublicPayModel() {
                Body = _settings.Subject,
                OutTradeNo = outTradeNo,
                TotalAmount = (amount * 100).ToInt32(0),
                OpenId = openId

            });
            var response = _gateway.Execute(request);
            return response.OrderInfo;
        }
        /// <summary>
        /// 小程序微信支付
        /// </summary>
        /// <returns>The mini wechatpay order.</returns>
        /// <param name="outTradeNo">Out trade no.</param>
        /// <param name="amount">Amount.</param>
        /// <param name="openId">Open identifier.</param>
        /// <param name="appId">小程序appId</param>
        /// <param name="shopname"></param>
        /// <param name="shopno"></param>
		/// <param name="timeExpire">过期时间</param>
        public string CreateMiniWechatpayOrder(string outTradeNo, double amount, string openId, string appId, string shopname, string shopno, string timeExpire = "")
        {
            if (string.IsNullOrEmpty(shopname)) {
                shopname = "";
            }

            var miniAppPaysetting = _listminiAppSettings.Find(c => c.appid == appId);
            var merchart = new PaySharp.Wechatpay.Merchant {
                AppId = appId,
                MchId = miniAppPaysetting.MchId,
                Key = miniAppPaysetting.Key,
                AppSecret = miniAppPaysetting.AppSecret,
                SslCertPath = miniAppPaysetting.SslCertPath,//"Certs/apiclient_cert.p12",
                SslCertPassword = miniAppPaysetting.SslCertPassword,// "1233410002",
                NotifyUrl = miniAppPaysetting.NotifyUrl + "/" + appId,
            };
            PaySharp.Wechatpay.WechatpayGateway _gateway = new PaySharp.Wechatpay.WechatpayGateway(merchart);
            var request = new PublicPayRequest();
            request.NotifyUrl = miniAppPaysetting.NotifyUrl + "/" + appId;
            if (string.IsNullOrEmpty(timeExpire)) {
                timeExpire = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss", CultureInfo.CurrentCulture);
            }
            var SceneInfo = new { store_info = new { id = shopno, name = shopname } };
            request.AddGatewayData(new PaySharp.Wechatpay.Domain.PublicPayModel() {
                Attach = _settings.Subject + (shopname.Length > 0 ? "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture) : ""),
                Body = _settings.Subject + (shopname.Length > 0 ? "-" + shopname.Replace(_settings.Subject, "", StringComparison.CurrentCulture) : ""),
                OutTradeNo = outTradeNo,
                TotalAmount = (amount * 100).ToInt32(0),
                OpenId = openId,
                SceneInfo = JsonConvert.SerializeObject(SceneInfo),
                TimeExpire = timeExpire,
                DeviceInfo = shopno,
            });
            if (!string.IsNullOrEmpty(miniAppPaysetting.GatewayUrl)) {
                _gateway.GatewayUrl = miniAppPaysetting.GatewayUrl;
            }
            logger.Trace(JsonConvert.SerializeObject(request));
            var response = _gateway.Execute(request);
            if (response.ReturnCode == "FAIL") {
                logger.Error($"CreateMiniWechatpayOrder:{JsonConvert.SerializeObject(response)}");
                throw new ArgumentException(response.ReturnMsg);
            }
            
            return response.OrderInfo;
        }
    }
}
